package cn.turboinfo.dongying.api.provider.common.service.impl.user;

import cn.turboinfo.dongying.api.domain.common.service.role.RoleService;
import cn.turboinfo.dongying.api.domain.common.service.user.SysUserRoleService;
import cn.turboinfo.dongying.api.entity.admin.exception.user.SysUserRoleException;
import cn.turboinfo.dongying.api.entity.admin.pojo.role.Role;
import cn.turboinfo.dongying.api.entity.admin.pojo.user.SysUserRole;
import cn.turboinfo.dongying.api.entity.admin.pojo.user.SysUserRoleCreator;
import cn.turboinfo.dongying.api.entity.admin.pojo.user.SysUserRoleUpdater;
import cn.turboinfo.dongying.api.entity.common.exception.common.DataNotExistException;
import cn.turboinfo.dongying.api.provider.common.repository.database.user.SysUserRoleDAO;
import cn.turboinfo.dongying.api.provider.common.repository.database.user.SysUserRolePO;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import net.sunshow.toolkit.core.qbean.api.request.QPage;
import net.sunshow.toolkit.core.qbean.api.request.QRequest;
import net.sunshow.toolkit.core.qbean.api.response.QResponse;
import net.sunshow.toolkit.core.qbean.helper.component.request.QBeanCreatorHelper;
import net.sunshow.toolkit.core.qbean.helper.component.request.QBeanUpdaterHelper;
import net.sunshow.toolkit.core.qbean.helper.service.impl.AbstractQServiceImpl;
import org.springframework.data.domain.Page;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.function.Function;
import java.util.function.Supplier;
import java.util.stream.Collectors;

@Slf4j
@RequiredArgsConstructor
@Service
public class SysUserRoleServiceImpl extends AbstractQServiceImpl<SysUserRole> implements SysUserRoleService {
    private final SysUserRoleDAO sysUserRoleDAO;

    private final RoleService roleService;

    @Override
    public Optional<SysUserRole> getById(Long id) {
        return sysUserRoleDAO.findById(id).map(this::convertQBean);
    }

    @Override
    @Transactional
    public SysUserRole save(SysUserRoleCreator creator) throws SysUserRoleException {
        SysUserRolePO sysUserRolePO = new SysUserRolePO();

        QBeanCreatorHelper.copyCreatorField(sysUserRolePO, creator);

        return convertQBean(sysUserRoleDAO.save(sysUserRolePO));
    }

    @Override
    @Transactional
    public SysUserRole update(SysUserRoleUpdater updater) throws SysUserRoleException {
        SysUserRolePO sysUserRolePO = getEntityWithNullCheckForUpdate(updater.getUpdateId(), sysUserRoleDAO);

        QBeanUpdaterHelper.copyUpdaterField(sysUserRolePO, updater);

        return convertQBean(sysUserRolePO);
    }

    @Override
    public QResponse<SysUserRole> findAll(QRequest request, QPage requestPage) {
        return convertQResponse(findAllInternal(request, requestPage));
    }

    private Page<SysUserRolePO> findAllInternal(QRequest request, QPage requestPage) {
        return sysUserRoleDAO.findAll(convertSpecification(request), convertPageable(requestPage));
    }

    @Override
    public List<SysUserRole> findBySysUserId(Long sysUserId) {
        return sysUserRoleDAO.findBySysUserId(sysUserId).stream().map(this::convertQBean).collect(Collectors.toList());
    }


    @Override
    @Transactional
    public void delete(Long sysUserId, Long roleId) {
        sysUserRoleDAO.findBySysUserIdAndRoleId(sysUserId, roleId).ifPresent(sysUserRoleDAO::delete);
    }

    @Override
    @Transactional
    public void reassign(Long sysUserId, Collection<Long> roleIdCollection) {
        // 拿到已有的
        List<SysUserRolePO> sysUserRolePOList = sysUserRoleDAO.findBySysUserId(sysUserId);

        Map<Long, SysUserRolePO> roleIdSysUserRolePOMap = sysUserRolePOList.stream().collect(Collectors.toMap(SysUserRolePO::getRoleId, Function.identity()));

        // 要删除的部分
        sysUserRolePOList.stream().map(SysUserRolePO::getRoleId).filter(roleId -> !roleIdCollection.contains(roleId)).forEach(roleId -> {
            // 执行删除
            sysUserRoleDAO.delete(roleIdSysUserRolePOMap.get(roleId));
        });

        // 要新增的部分
        roleIdCollection.stream()
                .filter(roleId -> !roleIdSysUserRolePOMap.containsKey(roleId))
                .map(roleId -> {
                    SysUserRolePO po = new SysUserRolePO();
                    po.setRoleId(roleId);
                    po.setSysUserId(sysUserId);
                    return po;
                })
                .forEach(po -> sysUserRoleDAO.save(po));
    }

    @Override
    @Transactional
    public SysUserRole assignByCode(Long sysUserId, String code) {
        // 拿到角色
        Role role = roleService.getByCode(code).orElseThrow(DataNotExistException::new);
        // 拿到已有的
        Optional<SysUserRolePO> optional = sysUserRoleDAO.findBySysUserIdAndRoleId(sysUserId, role.getId());
        if (optional.isPresent()) {
            return convertQBean(optional.get());
        }
        SysUserRolePO po = new SysUserRolePO();
        po.setSysUserId(sysUserId);
        po.setRoleId(role.getId());
        return convertQBean(sysUserRoleDAO.save(po));
    }

    @Override
    protected Supplier<? extends RuntimeException> getExceptionSupplier(String message,
                                                                        Throwable cause) {
        return () -> new SysUserRoleException(message, cause);
    }
}
